-- WarriorArms.lua
-- Updated May 30, 2025 - Enhanced Structure from Hunter Survival
-- Mists of Pandaria module for Warrior: Arms spec


    local _, playerClass = UnitClass('player')
    if playerClass ~= 'WARRIOR' then return end

    local addon, ns = ...
    local Hekili = _G[ addon ]

    if not Hekili then return end

    local class, state = Hekili.Class, Hekili.State

    -- Safe initialization without triggering emulation unknown-key warnings (use rawget instead of state.field lookups).
    do
        local st = rawget( Hekili, "State" )
        if st then
            if rawget( st, "last_cast_time" ) == nil then rawset( st, "last_cast_time", {} ) end
            if rawget( st, "rage" ) == nil then rawset( st, "rage", { current = 0, max = 100, time_to_max = 0, per_second = 0 } ) end
            if rawget( st, "movement" ) == nil then rawset( st, "movement", { distance = 0, moving = false } ) end
            if rawget( st, "damage" ) == nil then rawset( st, "damage", { incoming_damage_3s = 0 } ) end
            if rawget( st, "last_ability" ) == nil then rawset( st, "last_ability", false ) end
            -- Placeholder stance value; false (not nil) to indicate explicitly 'unset' without triggering stance equality checks.
            -- current_stance: nil until detected; use event-driven SyncStance. Avoid boolean placeholder that can confuse stance checks.
            if rawget( st, "current_stance" ) == nil then
                local idx = type( GetShapeshiftForm ) == "function" and GetShapeshiftForm() or 0
                local map = { [1] = "battle", [2] = "defensive", [3] = "berserker" }
                rawset( st, "current_stance", map[ idx ] )
            end
        end
    end

    -- Local aliases to core state helpers (mirrors DK/Shaman pattern) to avoid undefined global references.
    local applyBuff, removeBuff, applyDebuff, removeDebuff = state.applyBuff, state.removeBuff, state.applyDebuff, state.removeDebuff
    local addStack, removeStack = state.addStack, state.removeStack
    local setCooldown = state.setCooldown
    local gain, spend = state.gain, state.spend
    local interrupt = state.interrupt

    -- Provide lightweight fallbacks if engine helpers are missing in emulation/test harness.
    if not addStack then
        addStack = function(aura, target, n)
            local b = state.buff[aura]
            if not b then return end
            b.stack = math.min((b.stack or 0) + (n or 1), b.max_stack or 99)
            b.up = b.stack > 0
        end
    end
    if not removeStack then
        removeStack = function(aura, n)
            local b = state.buff[aura]
            if not b then return end
            b.stack = math.max(0, (b.stack or 0) - (n or 1))
            if b.stack == 0 then b.up = false end
        end
    end
    if not setCooldown then
        setCooldown = function(name, value)
            if state.cooldown[name] then
                state.cooldown[name].expires = state.query_time + (value or 0)
            end
        end
    end
    if not interrupt then
        interrupt = function() end
    end

    -- (Removed direct state.* initialization above in favor of rawget block.)

    local FindUnitBuffByID, FindUnitDebuffByID = ns.FindUnitBuffByID, ns.FindUnitDebuffByID
    local GetTargetDebuffByID = ns.GetTargetDebuffByID or function(id, caster)
        if FindUnitDebuffByID then
            local name, icon, count, debuffType, duration, expirationTime, unitCaster = FindUnitDebuffByID("target", id, caster or "PLAYER")
            if name then
                return { name = name, icon = icon, count = count or 1, duration = duration, expires = expirationTime, applied = expirationTime - duration, caster = unitCaster }
            end
        end
        return nil
    end
    local PTR = ns.PTR

    local strformat = string.format

    local spec = Hekili:NewSpecialization( 71 )

local combatLogFrame = CreateFrame("Frame")
local combatLogEvents = {}

local function RegisterCombatLogEvent(event, handler)
    if not combatLogEvents[event] then
        combatLogEvents[event] = {}
    end
    table.insert(combatLogEvents[event], handler)
end

-- Per-spec (Arms) handling; no shared Warrior file. Incoming damage-based Berserker stance rage is generated by the game itself,
-- so we don't simulate it; this frame only supports spec-specific tracking hooks below.

combatLogFrame:SetScript("OnEvent", function(self, event, ...)
    if event ~= "COMBAT_LOG_EVENT_UNFILTERED" then return end
    local fullInfo = { CombatLogGetCurrentEventInfo() }
    local timestamp, subevent, _, sourceGUID, _, _, _, destGUID = unpack(fullInfo)

    if sourceGUID == UnitGUID("player") then
        local handlers = combatLogEvents[subevent]
        if handlers then
            for _, handler in ipairs(handlers) do
                handler(timestamp, subevent, unpack(fullInfo, 5))
            end
        end
    end

end)

combatLogFrame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")

-- Colossus Smash debuff tracking
RegisterCombatLogEvent("SPELL_AURA_APPLIED", function(timestamp, subevent, sourceGUID, sourceName, sourceFlags, sourceRaidFlags, destGUID, destName, destFlags, destRaidFlags, spellID, spellName, spellSchool)
    if spellID == 86346 then -- Colossus Smash
        -- Track Colossus Smash debuff for optimal damage window
    elseif spellID == 85288 then -- Raging Blow (berserker stance proc)
        -- Track Raging Blow availability
    elseif spellID == 12292 then -- Bloodbath
        -- Track Bloodbath DoT application
    end
end)

-- Overpower proc tracking
RegisterCombatLogEvent("SPELL_AURA_APPLIED", function(timestamp, subevent, sourceGUID, sourceName, sourceFlags, sourceRaidFlags, destGUID, destName, destFlags, destRaidFlags, spellID, spellName, spellSchool)
    if spellID == 60503 then -- Taste for Blood (Overpower proc)
        -- Track Overpower proc availability
    elseif spellID == 46916 then -- Slam! proc
        -- Track Slam instant cast proc
    end
end)

-- Critical strike tracking for Deep Wounds
RegisterCombatLogEvent("SPELL_DAMAGE", function(timestamp, subevent, sourceGUID, sourceName, sourceFlags, sourceRaidFlags, destGUID, destName, destFlags, destRaidFlags, spellID, spellName, spellSchool, amount, overkill, school, resisted, blocked, absorbed, critical)
    if critical and (spellID == 12294 or spellID == 1464 or spellID == 78 or spellID == 845) then -- Mortal Strike, Slam, Heroic Strike, Cleave
        -- Apply Deep Wounds DoT on critical strikes
    end
end)

-- Target death tracking for DoT effects
RegisterCombatLogEvent("UNIT_DIED", function(timestamp, subevent, sourceGUID, sourceName, sourceFlags, sourceRaidFlags, destGUID, destName, destFlags, destRaidFlags)
    -- Handle target death for DoT effect optimization (Deep Wounds, Rend)
end)


-- Lightweight stance synchronization: check visible stance auras on player when UNIT_AURA fires.
do
    -- Stance detection: Use GetShapeshiftForm() index first (reliable even if aura not shown), fallback to aura IDs.
    local STANCE_IDS = { battle = 2457, defensive = 71, berserker = 2458 }
    local INDEX_TO_STANCE = { [1] = "battle", [2] = "defensive", [3] = "berserker" }

    local function HasPlayerAuraByID( id )
        for i = 1, 40 do
            local name, _, _, _, _, _, _, _, _, spellId = UnitBuff( "player", i )
            if not name then break end
            if spellId == id then return true end
        end
        return false
    end

    local function DetectStance()
        -- Prefer direct form info with spellID (most reliable).
        if GetNumShapeshiftForms and GetShapeshiftFormInfo then
            local num = GetNumShapeshiftForms()
            for i = 1, num do
                local _, name, isActive, _, spellID = GetShapeshiftFormInfo(i)
                if isActive and spellID then
                    if spellID == STANCE_IDS.battle then return "battle" end
                    if spellID == STANCE_IDS.defensive then return "defensive" end
                    if spellID == STANCE_IDS.berserker then return "berserker" end
                end
            end
        end
        -- Fallback to index mapping if form info didn't yield a result.
        local idx = GetShapeshiftForm and GetShapeshiftForm() or 0
        if idx and idx > 0 then
            local mapped = INDEX_TO_STANCE[ idx ]
            if mapped then return mapped end
        end
        -- Aura fallback if everything else fails.
        for key, id in pairs( STANCE_IDS ) do if HasPlayerAuraByID( id ) then return key end end
        return nil
    end

    local function SyncStance()
        local prev = state.current_stance
        local detected = DetectStance()
        if detected ~= prev then
            state.current_stance = detected
            -- Also sync synthetic stance buffs so any code relying on buff.* stays consistent.
            local b = state.buff
            if b then
                b.battle_stance.up     = detected == "battle"
                b.defensive_stance.up  = detected == "defensive"
                b.berserker_stance.up  = detected == "berserker"
                if detected == "battle" then
                    b.defensive_stance.up = false; b.berserker_stance.up = false
                elseif detected == "defensive" then
                    b.battle_stance.up = false; b.berserker_stance.up = false
                elseif detected == "berserker" then
                    b.battle_stance.up = false; b.defensive_stance.up = false
                end
            end
        end
        if not detected then state.current_stance = nil end
    end

    local f = CreateFrame("Frame")
    f:RegisterEvent("UNIT_AURA")
    f:RegisterEvent("UPDATE_SHAPESHIFT_FORM")
    f:RegisterEvent("PLAYER_ENTERING_WORLD")
    f:SetScript("OnEvent", function( self, event, unit )
        if event == "UNIT_AURA" and unit ~= "player" then return end
        SyncStance()
    end)

    C_Timer.After( 0.2, SyncStance )
    -- Poll as safety in case events do not fire for stance changes.
    C_Timer.NewTicker( 2, SyncStance )

    -- Simple slash debug (no dependency on profile debug flags): /hstance
    SLASH_HEKILISTANCE1 = "/hstance"
    SlashCmdList.HEKILISTANCE = function( msg )
        SyncStance() -- force update before reporting
        local idx = GetShapeshiftForm and GetShapeshiftForm() or 0
        local base = string.format( "[Hekili Stance] idx=%s -> mapped=%s (state=%s)", tostring(idx), tostring(INDEX_TO_STANCE[idx] or 'nil'), tostring(state.current_stance) )
        if msg and msg:lower():find("full") then
            local b = state.buff
            local forms = {}
            if GetNumShapeshiftForms and GetShapeshiftFormInfo then
                local num = GetNumShapeshiftForms()
                for i = 1, num do
                    local fName, fName2, isActive, isCastable, spellID = GetShapeshiftFormInfo(i)
                    forms[#forms+1] = string.format("[%d] id=%s active=%s name1=%s name2=%s", i, tostring(spellID), tostring(isActive), tostring(fName), tostring(fName2))
                end
            end
            local detail = string.format( " | buffs: battle=%s defensive=%s berserker=%s | expr: in_battle=%s in_defensive=%s in_berserker=%s | forms: %s",
                b and tostring(b.battle_stance and b.battle_stance.up) or 'nil',
                b and tostring(b.defensive_stance and b.defensive_stance.up) or 'nil',
                b and tostring(b.berserker_stance and b.berserker_stance.up) or 'nil',
                tostring(state.current_stance == 'battle'),
                tostring(state.current_stance == 'defensive'),
                tostring(state.current_stance == 'berserker'),
                table.concat(forms, "; ") )
            base = base .. detail
        end
        if Hekili and Hekili.Print then Hekili:Print( base ) else print( base ) end
    end
end


spec:RegisterResource( 1, {
    -- MoP Stance-based rage generation (approximation of swing-based model)
    -- Weapon swing rage (per design feedback):
    --   Berserker: 1.75 * base_weapon_speed rage per main-hand swing -> 1.75 rage/sec
    --   Battle: Double Berserker -> 3.5 rage/sec
    --   Defensive: No rage from auto-attacks; passive +1 every 3s
    -- We model these as periodic regen ticks for prediction purposes.
    battle_stance_regen = {
        aura = "battle_stance",
        last = function ()
            local app = state.buff.battle_stance.applied
            local t = state.query_time
            return app + floor( ( t - app ) / 1 ) * 1
        end,
        interval = 1,
        value = function()
            if not state.combat or state.current_stance ~= "battle" then return 0 end
            -- Approximate average rage/sec while in battle stance.
            return 3.5
        end,
    },

    berserker_stance_regen = {
        aura = "berserker_stance",
        last = function ()
            local app = state.buff.berserker_stance.applied
            local t = state.query_time
            return app + floor( ( t - app ) / 1 ) * 1
        end,
        interval = 1,
        value = function()
            if not state.combat or state.current_stance ~= "berserker" then return 0 end
            -- Baseline berserker stance rage/sec.
            return 1.75
        end,
    },

    defensive_stance_regen = {
        aura = "defensive_stance",
        last = function ()
            local app = state.buff.defensive_stance.applied
            local t = state.query_time
            return app + floor( ( t - app ) / 3 ) * 3
        end,
        interval = 3,
        value = function()
            -- Defensive stance: fixed +1 rage every 3s; no auto-attack rage.
            if not state.buff.defensive_stance.up then return 0 end
            return 1
        end,
    },

    -- NOTE: Rage from damage taken only occurs in Berserker Stance (1 rage per 1% health lost).
    -- Predicting incoming damage is outside current scope; could be added later using recent damage sampling.

    -- Mortal Strike rage generation (MoP: generates 10 rage instead of costing rage)
    mortal_strike_regen = {
        last = function ()
            local lct = state.last_cast_time; return (lct and lct.mortal_strike) or 0
        end,
        interval = 6, -- Mortal Strike cooldown
        value = function()
            return (state.last_ability and state.last_ability == "mortal_strike") and 10 or 0
        end,
    },

    -- Berserker Rage rage generation (improved)
    berserker_rage = {
        aura = "berserker_rage",
        last = function ()
            local app = state.buff.berserker_rage.applied
            local t = state.query_time
            return app + floor( ( t - app ) / 1 ) * 1
        end,
        interval = 1,
        value = function()
            return state.buff.berserker_rage.up and 5 or 0 -- 5 rage per second during Berserker Rage
        end,
    },

    -- Deadly Calm rage efficiency (effectively rage generation)
    deadly_calm = {
        aura = "deadly_calm",
        last = function ()
            local app = state.buff.deadly_calm.applied
            local t = state.query_time
            return app + floor( ( t - app ) / 1 ) * 1
        end,
        interval = 1,
        value = function()
            -- Abilities cost no rage during Deadly Calm (effective rage generation)
            return state.buff.deadly_calm.up and 15 or 0
        end,
    },

    -- Charge rage generation (MoP: Juggernaut talent gives 15 rage per charge)
    charge_rage = {
        last = function ()
            local lct = state.last_cast_time; return (lct and lct.charge) or 0
        end,
        interval = 20, -- Charge cooldown
        value = function()
            return (state.last_ability and state.last_ability == "charge") and state.talent.juggernaut.enabled and 15 or 0
        end,
    },

    -- Victory Rush/Impending Victory rage generation
    victory_rush_rage = {
        last = function ()
            local lct = state.last_cast_time; return (lct and (lct.victory_rush or lct.impending_victory)) or 0
        end,
        interval = 1,
        value = function()
            local last_victory = (state.last_ability and state.last_ability == "victory_rush") or (state.last_ability and state.last_ability == "impending_victory")
            return last_victory and 5 or 0 -- 5 rage from Victory Rush abilities
        end,
    },
} )

-- Tier sets
spec:RegisterGear( 13, 1, { -- Tier 14 (Heart of Fear)
    { 85316, head = 85316, shoulder = 85319, chest = 85317, hands = 85318, legs = 85320 }, -- LFR
    { 85329, head = 85329, shoulder = 85332, chest = 85330, hands = 85331, legs = 85333 }, -- Normal
    { 86590, head = 86590, shoulder = 86593, chest = 86591, hands = 86592, legs = 86594 }, -- Heroic
} )

spec:RegisterAura( "tier14_2pc_arms", {
    id = 105771,
    duration = 30,
    max_stack = 1,
} )

spec:RegisterAura( "tier14_4pc_arms", {
    id = 105785,
    duration = 8,
    max_stack = 1,
} )

spec:RegisterGear( 14, 1, { -- Tier 15 (Throne of Thunder)
    { 95298, head = 95298, shoulder = 95301, chest = 95299, hands = 95300, legs = 95302 }, -- LFR
    { 95705, head = 95705, shoulder = 95708, chest = 95706, hands = 95707, legs = 95709 }, -- Normal
    { 96101, head = 96101, shoulder = 96104, chest = 96102, hands = 96103, legs = 96105 }, -- Heroic
} )

spec:RegisterAura( "tier15_2pc_arms", {
    id = 138165,
    duration = 20,
    max_stack = 1,
} )

spec:RegisterAura( "tier15_4pc_arms", {
    id = 138173,
    duration = 12,
    max_stack = 1,
} )

spec:RegisterGear( 15, 1, { -- Tier 16 (Siege of Orgrimmar)
    { 99691, head = 99691, shoulder = 99694, chest = 99692, hands = 99693, legs = 99695 }, -- LFR
    { 98342, head = 98342, shoulder = 98345, chest = 98343, hands = 98344, legs = 98346 }, -- Normal
    { 99236, head = 99236, shoulder = 99239, chest = 99237, hands = 99238, legs = 99240 }, -- Heroic
    { 99926, head = 99926, shoulder = 99929, chest = 99927, hands = 99928, legs = 99930 }, -- Mythic
} )

spec:RegisterAura( "tier16_2pc_arms", {
    id = 144438,
    duration = 30,
    max_stack = 1,
} )

spec:RegisterAura( "tier16_4pc_arms", {
    id = 144440,
    duration = 15,
    max_stack = 5,
} )

-- Legendary and Notable Items
spec:RegisterGear( "legendary_cloak", 102246, { -- Oxheart, Fearbreaker of Garrosh
    back = 102246,
} )

spec:RegisterAura( "legendary_cloak_proc", {
    id = 148010,
    duration = 4,
    max_stack = 1,
} )

spec:RegisterGear( "thoks_tail_tip", 104769, {
    trinket1 = 104769,
    trinket2 = 104769,
} )

spec:RegisterGear( "sigil_of_rampage", 104770, {
    trinket1 = 104770,
    trinket2 = 104770,
} )

spec:RegisterGear( "ticking_ebon_detonator", 104810, {
    trinket1 = 104810,
    trinket2 = 104810,
} )

spec:RegisterGear( "gorehowl", 105531, {
    main_hand = 105531,
} )

-- Comprehensive Talent System (MoP Talent Trees)
spec:RegisterTalents( {
    -- Tier 1 (Level 15) - Mobility
    juggernaut                 = { 1, 1, 103826 }, -- Your Charge ability has 2 charges, shares charges with Intervene, and generates 15 Rage.
    double_time                = { 1, 2, 103827 }, -- Your Charge ability has 2 charges, shares charges with Intervene, and no longer generates Rage.
    warbringer                 = { 1, 3, 103828 }, -- Charge also roots the target for 4 sec, and Hamstring generates more Rage.

    -- Tier 2 (Level 30) - Healing/Survival
    second_wind                = { 2, 1, 29838 },  -- While below 35% health, you regenerate 3% of your maximum health every 1 sec.
    enraged_regeneration       = { 2, 2, 55694 },  -- Instantly heals you for 10% of your total health and regenerates an additional 10% over 5 sec.
    impending_victory          = { 2, 3, 103840 }, -- Instantly attack the target causing damage and healing you for 10% of your maximum health.

    -- Tier 3 (Level 45) - Utility
    staggering_shout           = { 3, 1, 107566 }, -- Causes all enemies within 10 yards to have their movement speed reduced by 50% for 15 sec.
    piercing_howl              = { 3, 2, 12323 },  -- Causes all enemies within 10 yards to have their movement speed reduced by 50% for 15 sec.
    disrupting_shout           = { 3, 3, 102060 }, -- Interrupts all enemy spell casts and prevents any spell in that school from being cast for 4 sec.

    -- Tier 4 (Level 60) - Survivability
    bladestorm                 = { 4, 1, 46924 },  -- Become a whirling maelstrom of steel, striking all nearby enemies for weapon damage over 6 sec.
    shockwave                  = { 4, 2, 46968 },  -- Sends a wave through the ground, causing damage and stunning all enemies within 10 yards for 4 sec.
    dragon_roar                = { 4, 3, 118000 }, -- Roar with the fury of a dragon, dealing damage to all enemies within 8 yards.

    -- Tier 5 (Level 75) - Berserker Powers
    mass_spell_reflection      = { 5, 1, 114028 }, -- Reflects the next spell cast on you or your party members back at its caster.
    safeguard                  = { 5, 2, 114029 }, -- Intervene now removes all movement impairing effects and provides 30% damage reduction.
    vigilance                  = { 5, 3, 114030 }, -- Focus your protective instincts on a party member, reducing their damage taken by 30%.

    -- Tier 6 (Level 90) - Ultimate Abilities
    avatar                     = { 6, 1, 107574 }, -- Transform into a colossus for 24 sec, becoming immune to movement effects and increasing damage by 20%.
    bloodbath                  = { 6, 2, 12292 },  -- Your attacks trigger a bleeding DoT that lasts 1 min and stacks up to 3
    storm_bolt                 = { 6, 3, 107570 }, -- Hurls your weapon at an enemy, stunning them for 4 sec.
} )


spec:RegisterGlyphs( {
    -- Major Glyphs (affecting DPS and mechanics)
    [58095] = "Glyph of Berserker Rage",      -- Berserker Rage increases movement speed by 50% for its duration.
    [58096] = "Glyph of Bloodthirst",         -- Your Bloodthirst ability heals you for an additional 1% of your maximum health.
    [58097] = "Glyph of Bloody Healing",      -- Increases the healing received from Bloodthirst by 40%.
    [58098] = "Glyph of Bull Rush",           -- Charge now moves you a greater distance and through enemies.
    [58099] = "Glyph of Cleaving",            -- Your Cleave ability affects 1 additional target.
    [58100] = "Glyph of Colossus Smash",      -- Your Colossus Smash generates 10 additional Rage when it critically strikes.
    [58101] = "Glyph of Demoralizing Shout",  -- Reduces the rage cost of Demoralizing Shout by 50%.
    [58102] = "Glyph of Die by the Sword",    -- Die by the Sword also reflects damage back to attackers.
    [58103] = "Glyph of Enraged Speed",       -- Enrage increases your movement speed by 30%.
    [58104] = "Glyph of Execute",             -- Your Execute hits up to 2 additional enemies for 50% damage.
    [58105] = "Glyph of Hamstring",           -- Your Hamstring ability also reduces the target's damage by 10%.
    [58106] = "Glyph of Heroic Strike",       -- Your Heroic Strike increases the damage of your next ability by 15%.
    [58107] = "Glyph of Hindering Strikes",   -- Your auto attacks have a chance to reduce enemy movement speed by 50%.
    [58108] = "Glyph of Intimidating Shout",  -- Reduces the cooldown on Intimidating Shout by 15 sec.
    [58109] = "Glyph of Long Charge",         -- Increases the range of your Charge ability by 5 yards.
    [58110] = "Glyph of Mortal Strike",       -- Your Mortal Strike ability spreads its healing absorption to 1 nearby enemy.
    [58111] = "Glyph of Overpower",           -- Overpower has a 25% chance to reset the cooldown on Mortal Strike.
    [58112] = "Glyph of Raging Blow",         -- Raging Blow has no cooldown, but the rage cost is increased by 100%.
    [58113] = "Glyph of Rallying Cry",        -- Rallying Cry grants an additional 10% maximum health.
    [58114] = "Glyph of Rend",                -- Your Rend ability affects all enemies within 5 yards of your target.
    [58115] = "Glyph of Revenge",             -- Revenge also increases your movement speed by 30% for 6 sec.
    [58116] = "Glyph of Shield Slam",         -- Shield Slam silences the target for 3 sec.
    [58117] = "Glyph of Shield Wall",         -- Shield Wall reflects 20% of damage back to attackers.
    [58118] = "Glyph of Slam",                -- Slam has a 25% chance to reset the cooldown on Overpower.
    [58119] = "Glyph of Spell Reflection",    -- Spell Reflection lasts 50% longer.
    [58120] = "Glyph of Sweeping Strikes",    -- Increases the duration of Sweeping Strikes by 4 sec.
    [58121] = "Glyph of Thunder Clap",        -- Thunder Clap also reduces attack speed by an additional 10%.
    [58122] = "Glyph of Victory Rush",        -- Victory Rush increases your movement speed by 50% for 6 sec.
    [58123] = "Glyph of Whirlwind",           -- Whirlwind generates 5 rage for each target hit.
    [58124] = "Glyph of Wind and Thunder",    -- Reduces the rage cost of Thunder Clap by 10.

    -- Minor Glyphs (convenience and visual)
    [58125] = "Glyph of Battle",              -- You appear to be in a battle stance even when you're not.
    [58126] = "Glyph of Berserker Stance",    -- You appear to be in berserker stance even when you're not.
    [58127] = "Glyph of Bloodcurdling Shout", -- Your shouts have enhanced visual and sound effects.
    [58128] = "Glyph of Burning Anger",       -- Your character glows with inner fire when enraged.
    [58129] = "Glyph of Defensive Stance",    -- You appear to be in defensive stance even when you're not.
    [58130] = "Glyph of Gushing Wound",       -- Your critical strikes cause more dramatic bleeding effects.    [58131] = "Glyph of the Savage Beast",    -- Your weapons appear to drip with blood.
    [58132] = "Glyph of Thunder Strike",      -- Your weapon attacks create lightning effects.
    [58133] = "Glyph of the Weaponmaster",    -- Your weapons appear to be of exceptional quality.
    [58134] = "Glyph of Intimidation",        -- Your character appears more menacing.

    -- Missing glyphs referenced in abilities
    [58135] = "Glyph of Bladestorm",          -- Reduces the cooldown of Bladestorm by 15 sec.
    [58136] = "Glyph of Burning Anger",       -- Reduces the rage cost of Thunder Clap by 10.
    [58137] = "Glyph of Bull Rush",           -- Charge now moves you a greater distance and through enemies.
    [58138] = "Glyph of Long Charge",         -- Increases the range of your Charge ability by 5 yards.
    [58139] = "Glyph of Rallying Cry",        -- Rallying Cry grants an additional 10% maximum health.
    [58140] = "Glyph of Wind and Thunder",    -- Reduces the rage cost of Thunder Clap by 10.
    [58141] = "Glyph of Colossus Smash",      -- Your Colossus Smash generates 10 additional Rage when it critically strikes.
    [58142] = "Glyph of Overpower",           -- Overpower has a 25% chance to reset the cooldown on Mortal Strike.
    [58143] = "Glyph of Slam",                -- Slam has a 25% chance to reset the cooldown on Overpower.
    [58144] = "Glyph of Battle",              -- You appear to be in a battle stance even when you're not.
    [58145] = "Glyph of Bloody Healing",      -- Increases the healing received from Bloodthirst by 40%.
} )--]]

-- Arms Warrior specific auras
spec:RegisterAuras( {
    -- Core buffs/debuffs
    battle_shout = {
        id = 6673,
        duration = 3600,
        max_stack = 1,
    },
    commanding_shout = {
        id = 469,
        duration = 3600,
        max_stack = 1,
    },    colossus_smash = {
        id = 86346,
        duration = 6,
        max_stack = 1,
        generate = function( t )
            local name, icon, count, debuffType, duration, expirationTime, caster = FindUnitDebuffByID( "target", 86346 )

            if name then
                t.name = name
                t.count = count or 1
                t.expires = expirationTime
                t.applied = expirationTime - duration
                t.caster = caster
                return
            end

            t.count = 0
            t.expires = 0
            t.applied = 0
            t.caster = "nobody"
        end
    },
    mortal_wounds = {
        id = 12294,
        duration = 10,
        max_stack = 1,
    },
    sudden_death = {
        id = 52437,
        duration = 10,
        max_stack = 1,
    },
    taste_for_blood = {
        id = 60503,
        duration = 12,
        max_stack = 5
    },
    sweeping_strikes = {
        id = 12328,
        duration = 10,
        max_stack = 1,
    },    overpower = {
        id = 7384,
        duration = 5,  -- WoW Sims: 5 second window to use Overpower after dodge
        max_stack = 1,
    },
    deadly_calm = {
        id = 85730,
        duration = 10,
        max_stack = 1,
    },
    enrage = {
        id = 12880,
        duration = 8,
        max_stack = 1,
    },
    berserker_rage = {
        id = 18499,
        duration = 6,
        max_stack = 1,
    },

    -- Talent-specific buffs/debuffs
    avatar = {
        id = 107574,
        duration = 24,
        max_stack = 1,
    },
    bladestorm = {
        id = 46924,
        duration = 6,
        max_stack = 1,
    },
    bloodbath = {
        id = 12292,
        duration = 12,
        max_stack = 1,
    },
    bloodbath_dot = {
        id = 113344,
        duration = 6,
        tick_time = 1,
        max_stack = 1,
    },
    dragon_roar = {
        id = 118000,
        duration = 4,
        max_stack = 1,
    },
    second_wind = {
        id = 29838,
        duration = 3600,
        max_stack = 1,
    },
    vigilance = {
        id = 114030,
        duration = 12,
        max_stack = 1,
    },

    -- Defensives
    die_by_the_sword = {
        id = 118038,
        duration = function() return glyph.die_by_the_sword.enabled and 4 or 8 end,
        max_stack = 1,
    },
    shield_wall = {
        id = 871,
        duration = 12,
        max_stack = 1,
    },
    spell_reflection = {
        id = 23920,
        duration = function() return glyph.spell_reflection.enabled and 4 or 5 end,
        max_stack = 1,
    },
    mass_spell_reflection = {
        id = 114028,
        duration = 5,
        max_stack = 1,
    },
    enraged_regeneration = {
        id = 55694,
        duration = 5,
        tick_time = 1,
        max_stack = 1,
    },

    -- Crowd control / utility
    hamstring = {
        id = 1715,
        duration = 15,
        max_stack = 1,
    },
    piercing_howl = {
        id = 12323,
        duration = 15,
        max_stack = 1,
    },
    staggering_shout = {
        id = 107566,
        duration = 15,
        max_stack = 1,
    },
    shockwave = {
        id = 46968,
        duration = 4,
        max_stack = 1,
    },
    storm_bolt = {
        id = 107570,
        duration = 3,
        max_stack = 1,
    },
    war_banner = {
        id = 114207,
        duration = 15,
        max_stack = 1,
    },
    rallying_cry = {
        id = 97462,
        duration = 10,
        max_stack = 1,
    },
    demoralizing_shout = {
        id = 1160,
        duration = 10,
        max_stack = 1,
    },
    disrupting_shout = {
        id = 102060,
        duration = 4,
        max_stack = 1,
    },
    intimidating_shout = {
        id = 5246,
        duration = 8,
        max_stack = 1,
    },    charge_root = {
        id = 105771,
        duration = function()
            if talent.warbringer.enabled then
                return 4
            elseif glyph.bull_rush.enabled then
                return 1
            end
            return 0
        end,
        max_stack = 1,
    },
      -- DoTs and debuffs
    -- Arms signature: Colossus Smash damage window
    colossus_smash_window = {
        id = 86346, -- Same spell ID, but this is the player buff for damage calculations
        duration = 6,
        max_stack = 1,
    },
} )

-- Advanced Aura System with Generate Functions (following Hunter Survival pattern)
spec:RegisterAuras( {
    -- Arms-specific Auras
    mortal_strike = {
        id = 12294,
        duration = 10,
        max_stack = 1,
        generate = function( t )
            local name, icon, count, debuffType, duration, expirationTime, caster = FindUnitDebuffByID( "target", 12294 )
            if name then
                t.name = name
                t.count = count or 1
                t.expires = expirationTime
                t.applied = expirationTime - duration
                t.caster = caster
                return
            end

            t.count = 0
            t.expires = 0
            t.applied = 0
            t.caster = "nobody"
        end
    },

    rend = {
        id = 94009,
        duration = 15,
        tick_time = 3,
        max_stack = 1,
        generate = function( t )
            local name, icon, count, debuffType, duration, expirationTime, caster = FindUnitDebuffByID( "target", 94009 )
            if name then
                t.name = name
                t.count = count or 1
                t.expires = expirationTime
                t.applied = expirationTime - duration
                t.caster = caster
                return
            end

            t.count = 0
            t.expires = 0
            t.applied = 0
            t.caster = "nobody"
        end
    },

    deep_wounds = {
        id = 115767,
        duration = 12,
        tick_time = 3,
        max_stack = 1,
        generate = function( t )
            local name, icon, count, debuffType, duration, expirationTime, caster = FindUnitDebuffByID( "target", 115767 )
            if name then
                t.name = name
                t.count = count or 1
                t.expires = expirationTime
                t.applied = expirationTime - duration
                t.caster = caster
                return
            end

            t.count = 0
            t.expires = 0
            t.applied = 0
            t.caster = "nobody"
        end
    },

    -- Missing auras referenced in action lists
    mortal_wounds = {
        id = 115804,
        duration = 10,
        max_stack = 1,
    },

    sudden_execute = {
        id = 52437,
        duration = 10,
        max_stack = 1,
    },

    charge = {
        id = 100,
        duration = 1,
        max_stack = 1,
    },

    fear = {
        id = 5246,
        duration = 8,
        max_stack = 1,
    },

    victory_rush = {
        id = 34428,
        duration = 0,
        max_stack = 1,
    },

    blood_pact = {
        id = 6307,
        duration = 3600,
        max_stack = 1,
    },

    expose_armor = {
        id = 8647,
        duration = 30,
        max_stack = 5,
    },

    horn_of_winter = {
        id = 57330,
        duration = 300,
        max_stack = 1,
    },

    sunder_armor = {
        id = 7386,
        duration = 30,
        max_stack = 5,
    },

    -- Casting buff for spell reflection
    casting = {
        duration = function () return haste end,
        max_stack = 1,
        generate = function ()
            -- This is handled by the game's casting system
            return nil
        end,
    },

    taste_for_blood = {
        id = 60503,
        duration = 9,
        max_stack = 5,
        generate = function( t )
            local name, icon, count, debuffType, duration, expirationTime, caster = FindUnitBuffByID( "player", 60503 )

            if name then
                t.name = name
                t.count = count or 1
                t.expires = expirationTime
                t.applied = expirationTime - duration
                t.caster = caster
                return
            end

            t.count = 0
            t.expires = 0
            t.applied = 0
            t.caster = "nobody"
        end
    },

    slam_proc = {
        id = 46916,
        duration = 5,
        max_stack = 1,
        generate = function( t )
            local name, icon, count, debuffType, duration, expirationTime, caster = FindUnitBuffByID( "player", 46916 )

            if name then
                t.name = name
                t.count = count or 1
                t.expires = expirationTime
                t.applied = expirationTime - duration
                t.caster = caster
                return
            end

            t.count = 0
            t.expires = 0
            t.applied = 0
            t.caster = "nobody"
        end
    },

    sudden_death = {
        id = 52437,
        duration = 10,
        max_stack = 1,
        generate = function( t )
            local name, icon, count, debuffType, duration, expirationTime, caster = FindUnitBuffByID( "player", 52437 )

            if name then
                t.name = name
                t.count = count or 1
                t.expires = expirationTime
                t.applied = expirationTime - duration
                t.caster = caster
                return
            end

            t.count = 0
            t.expires = 0
            t.applied = 0
            t.caster = "nobody"
        end
    },

    bloodbath = {
        id = 113344,
        duration = 60,
        tick_time = 3,
        max_stack = 3,
        generate = function( t )
            local debuff = GetTargetDebuffByID(113344, "PLAYER")
            if debuff then
                t.name = debuff.name
                t.count = debuff.count
                t.expires = debuff.expires
                t.applied = debuff.applied
                t.caster = debuff.caster
                return
            end

            t.count = 0
            t.expires = 0
            t.applied = 0
            t.caster = "nobody"
        end
    },

    -- Shared Warrior Auras
    battle_stance = {
        id = 2457,
        duration = 3600,
    max_stack = 1
    },

    defensive_stance = {
        id = 71,
        duration = 3600,
    max_stack = 1
    },

    berserker_stance = {
        id = 2458,
        duration = 3600,
    max_stack = 1
    },

    berserker_rage = {
        id = 18499,
        duration = 6,
        max_stack = 1,
        generate = function( t )
            local name, icon, count, debuffType, duration, expirationTime, caster = FindUnitBuffByID( "player", 18499 )

            if name then
                t.name = name
                t.count = count or 1
                t.expires = expirationTime
                t.applied = expirationTime - duration
                t.caster = caster
                return
            end

            t.count = 0
            t.expires = 0
            t.applied = 0
            t.caster = "nobody"
        end
    },

    deadly_calm = {
        id = 85730,
        duration = 10,
        max_stack = 1,
        generate = function( t )
            local name, icon, count, debuffType, duration, expirationTime, caster = FindUnitBuffByID( "player", 85730 )

            if name then
                t.name = name
                t.count = count or 1
                t.expires = expirationTime
                t.applied = expirationTime - duration
                t.caster = caster
                return
            end

            t.count = 0
            t.expires = 0
            t.applied = 0
            t.caster = "nobody"
        end
    },

    avatar = {
        id = 107574,
        duration = 24,
        max_stack = 1,
        generate = function( t )
            local name, icon, count, debuffType, duration, expirationTime, caster = FindUnitBuffByID( "player", 107574 )

            if name then
                t.name = name
                t.count = count or 1
                t.expires = expirationTime
                t.applied = expirationTime - duration
                t.caster = caster
                return
            end

            t.count = 0
            t.expires = 0
            t.applied = 0
            t.caster = "nobody"
        end
    },

    sweeping_strikes = {
        id = 12328,
        duration = 10,
        max_stack = 1,
        generate = function( t )
            local name, icon, count, debuffType, duration, expirationTime, caster = FindUnitBuffByID( "player", 12328 )

            if name then
                t.name = name
                t.count = count or 1
                t.expires = expirationTime
                t.applied = expirationTime - duration
                t.caster = caster
                return
            end

            t.count = 0
            t.expires = 0
            t.applied = 0
            t.caster = "nobody"
        end
    },

    recklessness = {
        id = 1719,
        duration = 12,
        max_stack = 1,
        generate = function( t )
            local name, icon, count, debuffType, duration, expirationTime, caster = FindUnitBuffByID( "player", 1719 )

            if name then
                t.name = name
                t.count = count or 1
                t.expires = expirationTime
                t.applied = expirationTime - duration
                t.caster = caster
                return
            end

            t.count = 0
            t.expires = 0
            t.applied = 0
            t.caster = "nobody"
        end
    },

    shield_wall = {
        id = 871,
        duration = 12,
        max_stack = 1,
        generate = function( t )
            local name, icon, count, debuffType, duration, expirationTime, caster = FindUnitBuffByID( "player", 871 )

            if name then
                t.name = name
                t.count = count or 1
                t.expires = expirationTime
                t.applied = expirationTime - duration
                t.caster = caster
                return
            end

            t.count = 0
            t.expires = 0
            t.applied = 0
            t.caster = "nobody"
        end
    },

    die_by_the_sword = {
        id = 118038,
        duration = 8,
        max_stack = 1,
        generate = function( t )
            local name, icon, count, debuffType, duration, expirationTime, caster = FindUnitBuffByID( "player", 118038 )

            if name then
                t.name = name
                t.count = count or 1
                t.expires = expirationTime
                t.applied = expirationTime - duration
                t.caster = caster
                return
            end

            t.count = 0
            t.expires = 0
            t.applied = 0
            t.caster = "nobody"
        end
    },

    spell_reflection = {
        id = 23920,
        duration = 5,
        max_stack = 1,
        generate = function( t )
            local name, icon, count, debuffType, duration, expirationTime, caster = FindUnitBuffByID( "player", 23920 )

            if name then
                t.name = name
                t.count = count or 1
                t.expires = expirationTime
                t.applied = expirationTime - duration
                t.caster = caster
                return
            end

            t.count = 0
            t.expires = 0
            t.applied = 0
            t.caster = "nobody"
        end
    },

    rallying_cry = {
        id = 97462,
        duration = 10,
        max_stack = 1,
        generate = function( t )
            local name, icon, count, debuffType, duration, expirationTime, caster = FindUnitBuffByID( "player", 97462 )

            if name then
                t.name = name
                t.count = count or 1
                t.expires = expirationTime
                t.applied = expirationTime - duration
                t.caster = caster
                return
            end

            t.count = 0
            t.expires = 0
            t.applied = 0
            t.caster = "nobody"
        end
    },

    commanding_shout = {
        id = 469,
        duration = 300,
        max_stack = 1
    },

    battle_shout = {
        id = 6673,
        duration = 300,
        max_stack = 1
    },

    -- Missing auras referenced in APL
    war_banner = {
        id = 114207,
        duration = 15,
        max_stack = 1,
    },

    charge = {
        id = 100,
        duration = 1,
        max_stack = 1,
    },

} )

-- MoP Stance System - Abilities no longer require specific stances
spec:RegisterAbilities( {
    -- Core rotational abilities
       mortal_strike = {
        id = 12294,
        cast = 0,
        cooldown = 6,  -- MoP: 6 second cooldown
        gcd = "spell",

        spend = function()
            -- MoP: Mortal Strike generates 10 rage instead of costing rage
            return -10
        end,
        spendType = "rage",

        startsCombat = true,
        texture = 132355,

        handler = function()
            -- Apply Mortal Strike debuff (healing reduction)
            applyDebuff( "target", "mortal_wounds", 10 )
            -- Also apply Deep Wounds debuff
            applyDebuff( "target", "deep_wounds", 15 )
            -- Always add 2 stacks of Taste for Blood, max 5
            if not buff.taste_for_blood.up then
                applyBuff( "taste_for_blood" )
                buff.taste_for_blood.stack = 2
            else
                addStack( "taste_for_blood", nil, 2 )
                if buff.taste_for_blood.stack > 5 then
                    buff.taste_for_blood.stack = 5
                end
            end
        end,
    },
      overpower = {
        id = 7384,
        cast = 0,
        cooldown = 0,
        gcd = function() return 1.0 end,  -- MoP: Reduced global cooldown

        spend = function()
            return buff.sudden_execute.up and 0 or 10
        end,
        spendType = "rage",

        startsCombat = true,
        texture = 132223,

        charges = function()
            -- MoP: Works off a charge system
            return buff.taste_for_blood.stack or 0
        end,

        usable = function()
            return buff.taste_for_blood.up, "requires taste for blood charges (from mortal strike)"
        end,

        handler = function()
            removeStack( "taste_for_blood", 1 )

            -- Glyph of Overpower: 25% chance to reset Mortal Strike cooldown
            if glyph.overpower and glyph.overpower.enabled and math.random() < 0.25 then
                setCooldown( "mortal_strike", 0 )
            end
        end,
    },
      colossus_smash = {
        id = 86346,
        cast = 0,
        cooldown = 20,
        gcd = "spell",

        spend = 20,  -- MoP: 20 rage cost
        spendType = "rage",

        startsCombat = true,
        texture = 464973,

        handler = function()
            -- Apply the signature Colossus Smash debuff (6 seconds, ignores armor)
            applyDebuff( "target", "colossus_smash", 6 )

            -- MoP: Colossus Smash provides a damage window
            if glyph.colossus_smash and glyph.colossus_smash.enabled then
                applyBuff( "berserker_stance", 15 ) -- Glyph grants Berserker Stance benefits
            end

            -- Arms signature: Enhanced damage during Colossus Smash window
            applyBuff( "colossus_smash_window", 6 ) -- Player buff for damage calculations
        end,
    },


        execute = {
            id = 5308,
            cast = 0,
            cooldown = 0,
            gcd = "spell",
            spend = 30,
            spendType = "rage",
            startsCombat = true,
            texture = 135358,
            -- If hit on health less than 20% grant buff Sudden_death
            handler = function()
                applyBuff("sudden_execute")
            end,
        },

        slam = {
            id = 1464,
            cast = 0,  -- MoP: Slam is now instant cast
            cooldown = 0,
            gcd = "spell",

        spend = 25,  -- MoP: 25 rage cost
        spendType = "rage",

        startsCombat = true,
        texture = 132340,

        handler = function()
            -- MoP: Slam deals 275% weapon damage + 10% more during Colossus Smash
            -- Glyph of Slam: 25% chance to reset Overpower cooldown
            if glyph.slam and glyph.slam.enabled and math.random() < 0.25 then
                if not buff.taste_for_blood.up then
                    applyBuff( "taste_for_blood" )
                    buff.taste_for_blood.stack = 1
                else
                    addStack( "taste_for_blood", nil, 1 )
                end
            end

            -- MoP: While Sweeping Strikes is active, 35% of Slam damage hits all enemies within 2 yards
            if buff.sweeping_strikes.up then
                -- This is handled by the game engine
            end
        end,
    },
      rend = {
        id = 772,
        cast = 0,
        cooldown = 0,
        gcd = "spell",

        spend = 10,  -- WoW Sims: 10 rage cost
        spendType = "rage",

        startsCombat = true,
        texture = 132155,

        handler = function()
            applyDebuff( "target", "rend" )

            -- Trigger Taste for Blood (Arms passive that builds stacks on Rend/auto crit)
            if not buff.taste_for_blood.up then
                applyBuff( "taste_for_blood" )
                buff.taste_for_blood.stack = 1
            elseif buff.taste_for_blood.stack < 3 then
                addStack( "taste_for_blood", nil, 1 )
            end
        end,
    },

    -- Defensive / utility
    battle_shout = {
        id = 6673,
        cast = 0,
        cooldown = 0,
        gcd = "spell",

        spend = function()
            -- MoP: Battle Shout generates rage when used
            return -10
        end,
        spendType = "rage",

        startsCombat = false,
        texture = 132333,

        handler = function()
            -- Apply Battle Shout buff (increases attack power)
            applyBuff( "battle_shout", 300 ) -- 5 minute duration in MoP

            -- MoP: Battle Shout generates rage
            gain( 10, "rage" )

            -- Glyph of Battle: Additional health bonus
            if glyph.battle and glyph.battle.enabled then
                applyBuff( "battle_shout_health", 3600 ) -- 1 hour health bonus
            end

            -- Improved shouts from talents would affect party/raid here
            if talent.commanding_presence and talent.commanding_presence.enabled then
                -- Enhanced buff duration and effects
                buff.battle_shout.duration = 450 -- 7.5 minutes with talent
            end
        end,
    },

    commanding_shout = {
        id = 469,
        cast = 0,
        cooldown = 0,
        gcd = "spell",

        spend = function()
            -- MoP: Commanding Shout also generates rage when used
            return -10
        end,
        spendType = "rage",

        startsCombat = false,
        texture = 132351,

        handler = function()
            -- Apply Commanding Shout buff (increases stamina)
            applyBuff( "commanding_shout", 300 ) -- 5 minute duration in MoP

            -- MoP: Commanding Shout generates rage
            gain( 10, "rage" )

            -- Enhanced effects with talents
            if talent.commanding_presence and talent.commanding_presence.enabled then
                buff.commanding_shout.duration = 450 -- 7.5 minutes with talent
            end

            -- Glyph of Rallying Cry synergy
            if glyph.rallying_cry and glyph.rallying_cry.enabled then
                -- Commanding Shout provides additional health benefit
                applyBuff( "commanding_shout_health", 300 )
            end
        end,
    },
      sweeping_strikes = {
        id = 12328,
        cast = 0,
        cooldown = 10,  -- MoP: 10-second cooldown, can always maintain if you have rage
        gcd = "spell",

        spend = 20,  -- Rage cost to maintain
        spendType = "rage",

        startsCombat = false,
        texture = 132306,

        handler = function()
            applyBuff( "sweeping_strikes" )
            -- MoP: Sweeping Strikes now deals 50% damage to targets (down from 100%)
            -- MoP: While active, 35% of Slam damage hits all enemies within 2 yards
        end,
    },

       charge = {
         id = 1250619,
        cast = 0,
    cooldown = state.talent.juggernaut and state.talent.juggernaut.enabled and 12 or 20,
        gcd = "off",
        spend = function()
            local yards = movement.distance or 0
            if yards > 10 then yards = 10 end
            return - (10 + yards)
        end,
        spendType = "rage",
        range = 25,
        startsCombat = true,
        texture = 132337,
    },

    hamstring = {
        id = 1715,
        cast = 0,
        cooldown = 0,
        gcd = function() return glyph.hamstring.enabled and 0.5 or 1.5 end,

        spend = function()
            if talent.warbringer.enabled then return 5 end
            return 10
        end,
        spendType = "rage",

        startsCombat = true,
        texture = 132316,

        handler = function()
            applyDebuff( "target", "hamstring" )
        end,
    },
      deadly_calm = {
        id = 85730,
        cast = 0,
        cooldown = 60,
        gcd = "off",

        spend = 0,
        spendType = "rage",

        toggle = "cooldowns",

        startsCombat = false,
        texture = 464593,

        handler = function()
            applyBuff( "deadly_calm" )
        end,
    },

    berserker_rage = {
        id = 18499,
        cast = 0,
        cooldown = 30,
        gcd = "off",
        spend = 0,
        spendType = "rage",
        startsCombat = false,
        texture = 136009,

        handler = function()
            applyBuff( "berserker_rage" )
        end,
    },

    heroic_leap = {
        id = 6544,
        cast = 0,
        cooldown = 45,
        gcd = "spell",

        spend = 0,
        spendType = "rage",

        startsCombat = true,
        texture = 236171,

        handler = function()
            -- No specific effect, just the leap
        end,
    },

    rallying_cry = {
        id = 97462,
        cast = 0,
        cooldown = 180,
        gcd = "spell",

        spend = 0,
        spendType = "rage",

        toggle = "defensives",

        startsCombat = false,
        texture = 132351,

        handler = function()
            applyBuff( "rallying_cry" )
        end,
    },

    die_by_the_sword = {
        id = 118038,
        cast = 0,
        cooldown = 180,
        gcd = "off",

        spend = 0,
        spendType = "rage",

        toggle = "defensives",

        startsCombat = false,
        texture = 132336,

        handler = function()
            applyBuff( "die_by_the_sword" )
        end,
    },

    intervene = {
        id = 3411,
        cast = 0,
        cooldown = function()
            if talent.juggernaut and talent.juggernaut.enabled or talent.double_time and talent.double_time.enabled then
                return 20
            end
            return 30
        end,
        charges = function()
            if talent.juggernaut and talent.juggernaut.enabled or talent.double_time and talent.double_time.enabled then
                return 2
            end
            return 1
        end,
        recharge = function()
            if talent.juggernaut and talent.juggernaut.enabled or talent.double_time and talent.double_time.enabled then
                return 20
            end
            return 30
        end,
        gcd = "off",

        spend = 0,
        spendType = "rage",

        range = function()
            if glyph.long_charge and glyph.long_charge.enabled then
                return 30
            end
            return 25
        end,

        startsCombat = false,
        texture = 132365,

        handler = function()
            if talent.safeguard and talent.safeguard.enabled then
                -- Apply damage reduction to the target (handled by the game)
            end
        end,
    },

    -- Talent abilities
    avatar = {
        id = 107574,
        cast = 0,
        cooldown = 180,
        gcd = "spell",

        spend = 0,
        spendType = "rage",

        toggle = "cooldowns",

        startsCombat = false,
        texture = 613534,

        handler = function()
            applyBuff( "avatar" )
        end,
    },

    bloodbath = {
        id = 12292,
        cast = 0,
        cooldown = 60,
        gcd = "spell",

        spend = 0,
        spendType = "rage",

        toggle = "cooldowns",

        startsCombat = false,
        texture = 236304,

        handler = function()
            applyBuff( "bloodbath" )
        end,
    },

    bladestorm = {
        id = 46924,
        cast = 0,
        cooldown = function() return glyph.bladestorm and glyph.bladestorm.enabled and 75 or 90 end,
        gcd = "spell",

        spend = 0,
        spendType = "rage",

        toggle = "cooldowns",

        startsCombat = true,
        texture = 236303,

        handler = function()
            applyBuff( "bladestorm" )
        end,
    },

    dragon_roar = {
        id = 118000,
        cast = 0,
        cooldown = 60,
        gcd = "spell",

        spend = 0,
        spendType = "rage",

        toggle = "cooldowns",

        startsCombat = true,
        texture = 642418,

        handler = function()
            applyDebuff( "target", "dragon_roar" )
        end,
    },

    shockwave = {
        id = 46968,
        cast = 0,
        cooldown = 40,
        gcd = "spell",

        spend = function()
            if glyph.burning_anger and glyph.burning_anger.enabled then return 20 end
            return 0
        end,
        spendType = "rage",

        toggle = "cooldowns",

        startsCombat = true,
        texture = 236312,

        handler = function()
            applyDebuff( "target", "shockwave" )
        end,
    },

    storm_bolt = {
        id = 107570,
        cast = 0,
        cooldown = 30,
        gcd = "spell",

        spend = 0,
        spendType = "rage",

        toggle = "cooldowns",

        startsCombat = true,
        texture = 613535,

        handler = function()
            applyDebuff( "target", "storm_bolt" )
        end,
    },

    vigilance = {
        id = 114030,
        cast = 0,
        cooldown = 120,
        gcd = "spell",

        spend = 0,
        spendType = "rage",

        toggle = "cooldowns",

        startsCombat = false,
        texture = 236331,

        handler = function()
            applyBuff( "vigilance" )
        end,
    },

    impending_victory = {
        id = 103840,
        cast = 0,
        cooldown = 30,
        gcd = "spell",

        spend = 10,
        spendType = "rage",

        startsCombat = true,
        texture = 589768,

        handler = function()
            local heal_amount = health.max * (glyph.bloody_healing and glyph.bloody_healing.enabled and 0.2 or 0.1)
            gain( heal_amount, "health" )
        end,
    },

    staggering_shout = {
        id = 107566,
        cast = 0,
        cooldown = 40,
        gcd = "spell",

        spend = 0,
        spendType = "rage",

        startsCombat = true,
        texture = 132346,

        handler = function()
            applyDebuff( "target", "staggering_shout" )
        end,
    },

    piercing_howl = {
        id = 12323,
        cast = 0,
        cooldown = 30,
        gcd = "spell",

        spend = 0,
        spendType = "rage",

        startsCombat = true,
        texture = 132117,

        handler = function()
            applyDebuff( "target", "piercing_howl" )
        end,
    },

    disrupting_shout = {
        id = 102060,
        cast = 0,
    -- Use static 15s; handler manually syncs pummel to avoid recursive cooldown lookups.
    cooldown = 15,
        gcd = "spell",

        spend = 0,
        spendType = "rage",

        toggle = "interrupts",

        startsCombat = true,
        texture = 613534,

        handler = function()
            applyDebuff( "target", "disrupting_shout" )
            setCooldown( "pummel", 15 )
        end,
    },

    pummel = {
        id = 6552,
        cast = 0,
    -- Static 15s; handler syncs disrupting_shout.
    cooldown = 15,
        gcd = "off",

        spend = 0,
        spendType = "rage",

        toggle = "interrupts",

        startsCombat = true,
        texture = 132938,

        debuff = "casting",
        readyTime = state.timeToInterrupt,

        handler = function()
            interrupt()
            setCooldown( "disrupting_shout", 15 )
        end,
    },

    -- MoP-specific abilities
    thunder_clap = {
        id = 6343,
        cast = 0,
        cooldown = 6,
        gcd = "spell",

        spend = function()
            if glyph.wind_and_thunder and glyph.wind_and_thunder.enabled then return 10 end
            return 20
        end,
        spendType = "rage",

        startsCombat = true,
        texture = 136105,

        handler = function()
            -- MoP: With Blood and Thunder talent, applies Deep Wounds to all targets hit
            if talent.blood_and_thunder and talent.blood_and_thunder.enabled then
                applyDebuff( "target", "deep_wounds" )
            end

            -- Base Thunder Clap slow effect
            applyDebuff( "target", "thunder_clap_slow" )
        end,
    },

    deep_wounds = {
        id = 115767,
        cast = 0,
        cooldown = 0,
        gcd = "off",

        spend = 0,
        spendType = "rage",

        startsCombat = true,
        texture = 132090,

        -- Passive ability triggered by critical strikes
        handler = function()
            applyDebuff( "target", "deep_wounds" )
        end,
    },

    -- Missing abilities referenced in action lists
    heroic_throw = {
        id = 57755,
        cast = 0,
        cooldown = 0,
        gcd = "spell",
        school = "physical",
        startsCombat = true,
        handler = function()
            -- Ranged attack
        end,
    },

    auto_attack = {
        id = 6603,
        cast = 0,
        cooldown = 0,
        gcd = "off",
        school = "physical",
        startsCombat = true,
        handler = function()
            -- Auto attack handled by game
        end,
    },

    -- Stance switching abilities (core MoP mechanic)
    battle_stance = {
        id = 2457,
        cast = 0,
        cooldown = 1.5, -- MoP: 1.5 second GCD for stance switching
        gcd = "spell",

        spend = 0,
        spendType = "rage",

        startsCombat = false,
        texture = 132349,

    usable = function() return state.current_stance ~= "battle" end,

        handler = function()
            -- Remove other stances
            removeBuff( "defensive_stance" )
            removeBuff( "berserker_stance" )

            -- Apply Battle Stance
            applyBuff( "battle_stance" )
            -- Set immediately so predictions/conditions respond without waiting on events.
            state.current_stance = "battle"

            -- MoP: Stance switching incurs rage loss
            local rage_loss = ((state.rage and state.rage.current) or 0) * 0.25 -- Lose 25% of current rage
            spend( rage_loss, "rage" )
        end,
    },

    defensive_stance = {
        id = 71,
        cast = 0,
        cooldown = 1.5,
        gcd = "spell",

        spend = 0,
        spendType = "rage",

        startsCombat = false,
        texture = 132341,

    usable = function() return state.current_stance ~= "defensive" end,

        handler = function()
            -- Remove other stances
            removeBuff( "battle_stance" )
            removeBuff( "berserker_stance" )

            -- Apply Defensive Stance
            applyBuff( "defensive_stance" )
            state.current_stance = "defensive"

            -- MoP: Stance switching incurs rage loss
            local rage_loss = ((state.rage and state.rage.current) or 0) * 0.25
            spend( rage_loss, "rage" )
        end,
    },

    berserker_stance = {
        id = 2458,
        cast = 0,
        cooldown = 1.5,
        gcd = "spell",

        spend = 0,
        spendType = "rage",

        startsCombat = false,
        texture = 132275,

    usable = function() return state.current_stance ~= "berserker" end,

        handler = function()
            -- Remove other stances
            removeBuff( "battle_stance" )
            removeBuff( "defensive_stance" )

            -- Apply Berserker Stance
            applyBuff( "berserker_stance" )
            state.current_stance = "berserker"

            -- MoP: Stance switching incurs rage loss
            local rage_loss = ((state.rage and state.rage.current) or 0) * 0.25
            spend( rage_loss, "rage" )
        end,
    },

    -- Imported APL compatibility stubs (out-of-era or cross-spec actions)
    whirlwind = {
        id = 1680,
        cast = 0,
        cooldown = 0,
        gcd = "spell",
    spend = 30,
        spendType = "rage",
        startsCombat = true,
        texture = 132369,
        handler = function()
            -- AoE damage handled by engine. Glyph-driven rage handled elsewhere.
        end,
    },

    cleave = {
        id = 845,
        cast = 0,
        cooldown = 0,
        gcd = "spell",
        spend = 30,
        spendType = "rage",
        startsCombat = true,
        texture = 132338,
        handler = function()
            -- Frontal cleave; engine distributes damage.
        end,
    },

    heroic_strike = {
        id = 78,
        cast = 0,
        cooldown = 0,
        gcd = "off",
        spend = function()
            -- MoP: 30 rage baseline, free during Deadly Calm.
            if buff.deadly_calm and buff.deadly_calm.up then return 0 end
            return 30
        end,
        spendType = "rage",
        startsCombat = true,
        texture = 132282,
        handler = function()
            -- Off-GCD rage dump; no extra state besides potential glyphs.
        end,
    },

    last_stand = {
        id = 12975,
        cast = 0,
        cooldown = 180,
        gcd = "off",
        toggle = "defensives",
        spend = 0,
        spendType = "rage",
        startsCombat = false,
        texture = 135871,
        handler = function()
            -- Prot CD; included so imported APL lines don't error.
        end,
    },

    -- (Removed bag_of_tricks and lights_judgment from core table; will register conditionally below.)

    apply_poison = {
        id = 2823, -- Rogue Deadly Poison placeholder.
        cast = 0,
        cooldown = 0,
        gcd = "off",
        spend = 0,
        spendType = "rage",
        startsCombat = false,
        texture = 132273,
        handler = function()
            -- Irrelevant to Warrior; ignore.
        end,
    },

    -- Additional unsupported import actions now mapped
    recklessness = {
        id = 1719,
        cast = 0,
        cooldown = 300,
        gcd = "off",
        spend = 0,
        spendType = "rage",
        toggle = "cooldowns",
        startsCombat = true,
        texture = 132109,
        handler = function()
            applyBuff( "recklessness" )
        end,
    },

    shield_wall = {
        id = 871,
        cast = 0,
        cooldown = 240,
        gcd = "off",
        spend = 0,
        spendType = "rage",
        toggle = "defensives",
        startsCombat = false,
        texture = 132362,
        handler = function()
            applyBuff( "shield_wall" )
        end,
    },

    demoralizing_shout = {
        id = 1160,
        cast = 0,
        cooldown = 60,
        gcd = "spell",
        spend = 0,
        spendType = "rage",
    -- Mark as defensive/utility so the engine treats it as a valid suggested action category.
    toggle = "defensives",
        startsCombat = true,
        texture = 132366,
        handler = function()
            applyDebuff( "target", "demoralizing_shout" )
        end,
    },

    intimidating_shout = {
        id = 5246,
        cast = 0,
        cooldown = 90,
        gcd = "spell",
        spend = 0,
        spendType = "rage",
    toggle = "defensives",
        startsCombat = true,
        texture = 132154,
        handler = function()
            applyDebuff( "target", "fear" )
        end,
    },

    enraged_regeneration = {
        id = 55694,
        cast = 0,
        cooldown = 60,
        gcd = "off",
        spend = 0,
        spendType = "rage",
        toggle = "defensives",
        startsCombat = false,
        texture = 132345,
        handler = function()
            applyBuff( "enraged_regeneration" )
        end,
    },

    victory_rush = {
        id = 34428,
        cast = 0,
        cooldown = 0,
        gcd = "spell",
        spend = 0,
        spendType = "rage",
    toggle = "defensives",
        startsCombat = true,
        texture = 132342,
        handler = function()
            -- Healing handled externally; placeholder.
        end,
    },

    sunder_armor = {
        id = 7386,
        cast = 0,
        cooldown = 0,
        gcd = "spell",
        spend = 0,
        spendType = "rage",
    toggle = "utility",
        startsCombat = true,
        texture = 134955,
        handler = function()
            applyDebuff( "target", "sunder_armor" )
        end,
    },

    -- Missing abilities referenced in APL
    shattering_throw = {
        id = 64382,
        cast = 0,
        cooldown = 300,
        gcd = "spell",
        spend = 0,
        spendType = "rage",
        startsCombat = true,
        texture = 132337,
        handler = function()
            -- Removes immunities and absorbs from target
        end,
    },

    skull_banner = {
        id = 114207,
        cast = 0,
        cooldown = 180,
        gcd = "spell",
        spend = 0,
        spendType = "rage",
        toggle = "cooldowns",
        startsCombat = false,
        texture = 236303,
        handler = function()
            applyBuff( "war_banner" )
        end,
    },

} )

-- Range
spec:RegisterRanges( "mortal_strike", "charge", "heroic_throw", "heroic_strike" )

-- Options
spec:RegisterOptions( {
    enabled = true,

    aoe = 3,

    gcd = 1645,

    nameplates = true,
    nameplateRange = 8,

    damage = true,
    damageExpiration = 8,

    potion = "golemblood",

    package = "Arms",
} )

local NewFeature = "|TInterface\\OptionsFrame\\UI-OptionsFrame-NewFeatureIcon:0|t"


-- State Expressions for MoP Arms Warrior
spec:RegisterStateExpr( "rage_deficit", function()
    return ((state.rage and state.rage.max) or 100) - ((state.rage and state.rage.current) or 0)
end )

spec:RegisterStateExpr( "current_rage", function()
    return (state.rage and state.rage.current) or 0
end )

spec:RegisterStateExpr( "rage_time_to_max", function()
    return (state.rage and state.rage.time_to_max) or 0
end )

spec:RegisterStateExpr( "rage_per_second", function()
    return (state.rage and state.rage.per_second) or 0
end )

-- Average stance base rage/sec (excludes ability-specific and damage-taken gains).
spec:RegisterStateExpr( "stance_rage_per_second", function()
    local stance = state.current_stance
    if stance == "battle" then
        return state.combat and 3.5 or 0
    elseif stance == "berserker" then
        return state.combat and 1.75 or 0
    elseif stance == "defensive" then
        return 1/3 -- 1 rage every 3 seconds.
    end
    return 0
end )

spec:RegisterStateExpr( "should_use_execute", function()
    return target.health_pct <= 20
end )

-- APL compatibility: some imported lines reference is_execute_phase.
-- Treat execute phase as target below 20% HP (classic execute threshold).
spec:RegisterStateExpr( "is_execute_phase", function()
    return target.health_pct < 20
end )

-- Stance convenience expressions for APL clarity.
spec:RegisterStateExpr( "in_battle_stance", function()
    local b = state.buff
    return (b and b.battle_stance and b.battle_stance.up) or state.current_stance == "battle"
end )
spec:RegisterStateExpr( "in_defensive_stance", function()
    local b = state.buff
    return (b and b.defensive_stance and b.defensive_stance.up) or state.current_stance == "defensive"
end )
spec:RegisterStateExpr( "in_berserker_stance", function()
    local b = state.buff
    return (b and b.berserker_stance and b.berserker_stance.up) or state.current_stance == "berserker"
end )

spec:RegisterStateExpr( "no_stance", function()
    return state.current_stance == nil
end )

-- Expose current_stance itself as a safe state expression so accesses don't trigger Unknown key errors before it's set.
spec:RegisterStateExpr( "current_stance", function()
    return rawget( state, "current_stance" ) -- may be nil until detected or set by a stance ability/event.
end )


spec:RegisterStateExpr( "colossus_smash_remains", function()
    return debuff.colossus_smash.remains
end )

spec:RegisterStateExpr( "mortal_strike_remains", function()
    return cooldown.mortal_strike.remains
end )

spec:RegisterStateExpr( "overpower_charges", function()
    return buff.taste_for_blood.stack or 0
end )

spec:RegisterStateExpr( "sweeping_strikes_active", function()
    return buff.sweeping_strikes.up
end )

spec:RegisterStateExpr( "deep_wounds_remains", function()
    return debuff.deep_wounds.remains
end )

-- Avoid shadowing engine-provided active_enemies; expose arms_active_enemies if needed.
-- active_enemies handled centrally in State.lua; removed spec-local arms_active_enemies to avoid duplication.

spec:RegisterStateExpr( "incoming_damage_3s", function()
    return (state.damage and state.damage.incoming_damage_3s) or 0
end )

spec:RegisterStateExpr( "movement_distance", function()
    return (state.movement and state.movement.distance) or 0
end )

spec:RegisterStateExpr( "movement_moving", function()
    return (state.movement and state.movement.moving) or false
end )

spec:RegisterStateExpr( "target_time_to_die", function()
    return target.time_to_die or 0
end )

spec:RegisterStateExpr( "target_health_pct", function()
    return target.health_pct or 100
end )

spec:RegisterStateExpr( "health_pct", function()
    return health.pct or 100
end )



spec:RegisterStateExpr( "target_casting", function()
    return target.casting or false
end )

spec:RegisterStateExpr( "target_cast_interruptible", function()
    return target.cast_interruptible or false
end )

spec:RegisterStateExpr( "tank", function()
    -- Return tank information for group scenarios
    return {
        health = {
            pct = function()
                -- Find the tank in the group/raid
                local tank = nil
                if IsInGroup() then
                    for i = 1, GetNumGroupMembers() do
                        local unit = IsInRaid() and "raid" .. i or "party" .. i
                        if UnitExists(unit) and UnitGroupRolesAssigned(unit) == "TANK" then
                            tank = unit
                            break
                        end
                    end
                end

                if tank then
                    return UnitHealth(tank) / UnitHealthMax(tank) * 100
                end
                return 100 -- Default if no tank found
            end
        }
    }
end )

spec:RegisterPack( "Arms", 20251017, [[Hekili:LR12UnUrs7NLzgSc2jt0QJJ9giBGXtcWMb)5aIC2CNiPPAzX1uKcKuwJxiWN9)QQUjzZ(ajLT8KfyVysSizxv1vxDvF1HfdxC7I5l9Yyl(LrdgnD4GHx0F4hgnE04fZZEAlBX8TE(p4Dp8hrEBG)7ht2KIp8PWyVL4ItJ3L4dVyX872feM9trlUZmfhbF7wM)IF5IHlMVoy5sg)tzP(lMF76G0Cx8FE5UcwM7gVc(TFwqCuUByqAg86vXj5U)t2dbHb9xmNEijfbr3hYCY8sUNLbp4xOnglY7Uq2Yf3SyE8w4JGxnNtVfZF0ljaFl(xH7G)xwWgGLFxU7s2D7wTQVFCyCA6UuN0nEPR77TDByaBPJxgxMtc2Yj0)sqOcHdOdim5UNLgSzxOxg9J)mEp8t4tiMvUKZj5WHRA9tDc9sZC2LcICgO(o6Taj3)7GiVuhVeFViMZ2K4VeWs7NMb6uzMTI5LTML4qVifz34JMDjWHu)LSvb(bz5UZYDhnvMfSOLWE3b)kK(tuOFbzRRNvuUFs8YC354BPZN1b3VMLcCCBsqCsq2t5U7xZatKLX7r6bpIbsksjthKjSnEbrPKapS)uu0MAr0sy(paNsPrW)0eS4qKFaDqRZpnhSurleFpU56zIt8Vp39xHF(hP)X()a(KOL5U3eghV8o633NeVB75TlZ72M72dnE4Na9Lnv4BeCB8bLTrfvZ8czrz99E0dUH0x8jejF28RujXjkY)lAJ)3r7CWW7elcL0fLIlTkfVCgL(WUWqN78IIy0o(FyXWjlji6bwgSY0W4m5FFkKMAgI3YjnyhUpiBnAjIc2WbnlzJonssTD3iIXQoERDg5SAxYtkBGF3ZpWluw(pfIgkkQoqpbKTA7Wsszjpao4iwP68u5ZahTKBW678FmkHcZrHnWaRGBJhdGaG3uSQC3FNhie(RFG5Tme819jVWn1CzqBfwe3Bm4sI2eN109QdhYD9foWAY944C3ZPTNQVBTB2ljHZXhKTUF3MV7V(QC3pmOsLjrkI32CoVjobyoealj4bvn7ptVdcAqVKIAG7Qm4F5UfV8pJ3fTmvEZ8Msbwq890NuQZm(szf2esIv9dxiXXpYs2gVhCDOelzoA8hbNgYX0az(xlwapiZTRUb)Gy)oBktVkdSHzoGrMdDhKJfGR35xzv9Bx6TllozJZDXHQqEMJVamtH3iIP9dWzjkI)ESxI5BYcdLkA2j7es(S7rVW6J4UtsChdUjzSvTsIv2CONg6Trvjaps(8A5UecQhbfa1jiofUrENpVQUrmAk3Kt(oc9jTEV9AH7Vr2cbW(cZFxM6vM57qe5KBg8W7hl(if)mP0N5Se)kGNanRm0uENKFesESfzW21cjRFYYFJxeOm2ah4AsvdM4J56X2(Sr1vU1CUyq3QgAPrVpRccdXDNzpxi5Sf(WMQHhvWScHBXaA9lgq02UV7kBRPdum1XfQ6410cVCQK6voiG8LmipJ4a)sp1q4uN4vRCU3FjMNgYk7ixFJG2a6UmibV01X7YQFBbD7kj(YFirBY7MIOKTojEVmhXpfuXR82fAm9rjxouAIWwxIN(RX8onLZMSRkm10(fx)blrWBb)gufH2UBZgwOPSXQi0gWOyd51ds(1lYNrMLtLYAzxKd)VDW8J5zjlYjRyXMsittwxZ8cHBYB9fz3nOB8OW)IHeRQybU4hzoSi2Mam1zE0OorFVyMPSD6YsRxMadPSuEI6b48TrfWoHfLcIFk3UzlKNy8gWWZKLJr7Y63M5q)(tVemwcGe83()eyc)zEnpWYG8BqifexkGSBA)j9V8Ci8RhHlfd7wwEHBJVf(2ewiwecVeiS0nbZfK8SpgcoLUL27PN3HlznBqxSiyRdoIOu9RD70grR0Xkl0KzFxa7bB3T7WTg)JX6WKeVPuPOF5vKGqwLP6RDbJ(V2I8uDw09IW0oAgdLyXw1F6sjwANHDiZTg9g91P(iTwFMVk1hXEvAE5msT(iQi37Y15)QYDJaPAd)VzmZcqYvzb0zTzfcQXdKqq98qxRMPWWbeYpR1aYAYmuAlsWUlsPHPNmqh3DyAmYi1ken74R6aq9QDlqXlhycUCwJL)rw7RFgNzOEoDf0Cdvk5udAwRWiTgpVZGMZ4GS(F(OIP7zSTe(e6uqna1CXRl8vP6pIFTvHgcCv2IhExOhWdSijkm7MYxK7UlLoeL6XWhJ)rSXc0Nu1PH53w)Hu7gsbOJF8xR(CGIFpsswrDBe6NCxUcIx9r0S56RWuame1QGo1cBzcH)4IAtEMuaL6NhYFOKFeWl558BnNP(CjSMgnaqd)ZfvY0wXeTQ2LuHKQxXLyHMR4X3uePn39Bb9)deU0B4XdF2AUzL1NWwIzvrjQGqixcq54YcdqBPpLTgImcNg(HEBv0f3YFvU7NG3jsrH2WcZnX7TbSXb(ihb5RTFXq3XyQXSTfbMZc8FGuO2mKAm5TxtWSwpH(qtaE(AcZvfdZxByUA4o(RbNBdymE5CsfORgyJIpuUaZ1p3RxYCWJSbfLTcBB9kH1grDmiU5HbkIUPboZqenRxkMyeu0X7RjHTkHv)2QjDWeUHKIZe9o0ylmGFiZ7rv1ZNOhwesLakBxdzuji5i2mAaTwg1rvUmqBdGrFMP6PbF3S5Mo)S3OMoUlUCQgsxBaInup80Tm0MHG0P1jhvzXCMwMo(gBmfbT2R0fBG2ZArRljnBWpvlBYk6UFDqsi2xrIUTxiVgZwa)J(B8(cbTF8GMq4HG0AIMcCkLqFKZ6rprePIT2yD5vWej6wwqKFmoowol92a7aNP8M4i(yA)8n5Ud6lF9zzaZ5UNaKkGCSpoXycjw57uZ8DIf(or6w06aw4sN9EHT0aafoo2mhhBBNwXrk6g2dHLMYiXkdL1vjG0(eYv)KNmHVUzR3rh1z0q5ZigeqZlm4)uR6X29IQQZKifFYjw6KWUheUeA(TmHUSHdazNu4Ra76iMj4GwPXfsq4FmWhUx8KtYoLMvl)c(LJY250ClReTEsUFrdhP5zfcZ1sj)nrOlLIEw2gm7gVukOfO(tHWpY51uxcLuRbrWYFKfzCqc1qnzzgdAr6LM2HcdzffKXUgI1XaI5GFhnWRdUC0fGVxVKiW0eW0)tB2cWRqr4cLHzTF(NXEhfVkaRJX7kgbOJTpqF(DV0wbL)zGiV7D0xZBKvUl(7pZf30(Ln46BV6Vl7H(9bRU6ng9ZBCPQn8PA5g6HupleMlMn1WhZmVgayKZyHQMnSCVJQqq7uqr59pk6KPDXYUAG874nTLEN9E8kVaLou(ESSuxvCvgPJwlEVEARRxanrsmQCXmB0GwxVxmT26UPV(QrTUWA9uTMotPhQ8pVkEEPQForHc7rHUhE(lAYQRScQjGGCvKGhxEKZY79XBVkLL9EIu0j931wvm7kBQxKR6mQLAx2vwinV11PpHDtmN2Zai9FM0Uh9OvBxoQRDqZOglLYmSmkfcrNhJ63ADoQFBXGuBxcLR)ID5d86ym7F0nHnkZR7b)ANHQR070XPYQBiXmTkPCc5NCnoEE6m6iwFaLTZsm3piy(M3Jdw8vftn9ZJ5hfpg984bTb1gG5wocPHG(5XpR0TCAKFE0L2hVGXrUvjtma0O0rYM04k37mBY7HdTmSJZg3aNLASM0fgddQS9Rm8MEaPsYvqhrNPTlwA4qEJL2wF4qtTSE2KcpOh7WdBx0klerJgr0Jn2GwcTajuDDaHBW5tjACPdpDG9wp7AWUOQMQY2f6vATbAZ3KDFaGByFcePr1TOXBtpCOWASxl3kUU4cT5r61USibH0snY6z65IRIcMAFQD7OHxt2xJpCOrZVEnpaVLAgZtOBhV0w62V(m42XThEko7IbTBrWpUN2WxwRIOVxQUPxnSIaxovOZQpObn4XUlj4rMLZM0UWr5mxI0VCGz(T1u6wNbzM83oxjBtHz4RhsDBm4fHr3iMAdS8uGv2azpDaCRO5Rh02kE8AdQTItNi4SplqavsXPk8FH7wTrqZetLCS3sCMXdeElooF)fbNgoyqTGJTmqzgpM6AarUliIJ6uPZrugXf9zxAKmskUc9ttYSUl7QV504Sw6IZX5Mw4aMg8NZqGAIYHMQ691l(v0ZRjI)Y96QnhwQmuTXJv6ltTKKt0MN3Q3QmWvVvyR)26JC1BRM5Qp)UxYyxPUJQAFwn)MQJtupCvYLZBCVZoZYGxHVSGDNF4Wzf)TOqSwgTQZ57St3ysDA2PZaSGzgkdk3jM8qsjCRvFaPkkDr3g4jvrwESgudRzAiO69glJ)K(XxB4m4cWZaJHM(7d2rDWzYPdXbNEVEOnkmKEDrAiC1CAqzOnCqQ8P7zXAZgQ5P(rLFA4wS5(uZqAI5ltIj6PT7oQs)KEwMUNQcI0246ODBHwGoZarVN9Gekh7ceaw1kfOwSTW2H7y7CS(SVOs)wGD0I8EPM82HAeOQfhRsJAGZ015A4X4RQCCwmzwmTNo(mX1(UJtc)p48g8DJhORTpCW8kfbuKMMLsWw)SOnEkiSk6Ux1Pd25D(TykIvzx)goY4QKAgPYcU043x29CCjeEKEVbB9Epn(nW467AT46M0ySWa)qvxbRRSQAxi60tzYCqXrk8(hg0tFwsUUAos(gCoFSqAPPVrHQt1P6efQoXcrRgWgfAowNMJvLul0uEIBuOQ1nN(0Yy6o0Ow1EdTXatZqJ6w22ALgzgnTKLLipimkR5cbep9HOzx264KfZNVz3kWlhn5gl())]] )

-- Removed duplicate stance aura synthesis block; stance handled by early SyncStance logic.

-- Internal helper: Jin'ya's Arcane Proxies (Feather trinket)
spec:RegisterAura( "jinas_arcane_proxies", {
    id = 94510, -- ToT Feather trinket
    duration = 20,
    max_stack = 10,
    internal = true,
} )

-- Internal helper: Skull Banner (MoP raid cooldown)
spec:RegisterAura( "skull_banner", {
    id = 114207, -- Skull Banner spell ID
    duration = 10,
    max_stack = 1,
    internal = true,
} )
